/**
 */
package br.org.bertol.mestrado.engine.fitness;

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;

import br.org.bertol.mestrado.engine.optimisation.entity.AbstractUnit;

/**
 * Classe abstrata dos tipos de fitness do problema.
 * @author contaqualquer
 * @param <T>
 *            Tipo de objeto
 */
public abstract class AbstractCombinatorialFitness<T> implements Cloneable {

    /***/
    protected transient ArrayList<T> classes;
    /***/
    protected transient long         fitnessCount;

    /**
     * @param classess
     *            Classes
     */
    public AbstractCombinatorialFitness(final ArrayList<T> classess) {
        classes = classess;
    }

    /**
     * Calcula o peso para um determinado objetivo.
     * @param route
     *            TODO
     * @param objective
     *            Objetivo a ser caculado
     * @return TODO
     */
    public abstract boolean fitness(final List<T> route,
            final EnumMap<Objective, Number> objective);

    /**
     * {@inheritDoc}
     */
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    /****/
    public abstract void reset();

    /**
     * Critério de parada do problema.
     * @return true caso atingindo, false caso contrário
     */
    public abstract boolean stopCriteria();

    /**
     * Realiza uma melhora na solução.
     * @param unit
     *            Entrada
     * @param varags
     *            Parâmetros auxiliares. Variam conforme implementação do
     *            problema
     * @param <U>
     *            {@link AbstractUnit} Tip ode objeto derivado
     * @return TODO
     * @throws Exception
     *             Caso ocorrao algum erro na clonagem
     */
    public abstract <U extends AbstractUnit<T>> U doBetter(final U unit,
            final Object... varags)
            throws Exception;

    /**
     * @return the starterClasses
     */
    public final ArrayList<T> getClasses() {
        return classes;
    }

    /**
     * @return the fitnessCount
     */
    public final long getFitnessCount() {
        return fitnessCount;
    }

}
